package com.cxs.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cxs.common.exception.APIException;
import com.cxs.common.lang.Const;
import com.cxs.controller.base.BaseController;
import com.cxs.entity.User;
import com.cxs.entity.UserRole;
import com.cxs.service.IRoleService;
import com.cxs.service.IUserRoleService;
import com.cxs.service.IUserService;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author chaoxiaoshu
 * @since 2022-06-08
 */
@RestController
@RequestMapping("/sys/user")
public class UserController extends BaseController {

    @Autowired
    IUserService userService;

    @Autowired
    IRoleService roleService;

    @Autowired
    IUserRoleService userRoleService;

    @Autowired
    BCryptPasswordEncoder bCryptPasswordEncoder;

    @PreAuthorize("hasAuthority('sys:user:list')")
    @PostMapping("/list")
    public IPage<User> list(@RequestBody Map<String, Object> params) {
        /*
          {
            searchData={roles=[1, 2], status=[], phone=123},
            pageOption={current=1, size=10, total=11, sizes=[10, 20, 50, 100]},
            current=1,
            size=10
            }

            roles
            [1, 2]
            status
            []
            phone
            1233
        */
        QueryWrapper<User> query = new QueryWrapper<>();

        if (params.containsKey("searchData")) {
            Map<String, Object> searchData = (HashMap) params.get("searchData");
            for (String field : searchData.keySet()) {
                System.out.println(field);
                System.out.println(searchData.get(field).getClass().equals(ArrayList.class));
                if (searchData.get(field).getClass().equals(ArrayList.class)) {
                    ArrayList<String> arr = (ArrayList)searchData.get(field);
                    for (String value : arr) {
                        query.eq(field, value).or();

                    }
                } else if (searchData.get(field).getClass().equals(String.class)) {

                }

            }
            System.out.println(searchData);
        }

//        if (name != null) {
//            query.like("name", name)
//                    .or().like("username", name)
//                    .or().like("phone", name);
//        }
        IPage<User> page = userService.page(new Page<>(1, 10), query);
        for (User user : page.getRecords()) {
            user.setRoles(roleService.findRolesByUserId(user.getId()));
        }
        return page;
    }

    @GetMapping("/info/{id}")
    public User getUserInfo(@PathVariable Long id) {
        User user = userService.getById(id);
        user.setRoles(roleService.findRolesByUserId(user.getId()));
        return user;
    }

    /**
     * 添加用户
     * @param user
     * @return
     */
    @PreAuthorize("hasAuthority('sys:user:save')")
    @PostMapping("/save")
    public boolean saveUser(@RequestBody User user) {
        if (user.getName() == null) {
            throw new APIException("A0408", "姓名");
        }
        if (user.getUsername() == null) {
            throw new APIException("A0408", "用户名");
        }
        if (userService.getByUsername(user.getUsername()) != null) {
            throw new APIException("A0409", "用户名");
        }
        String passEncoder = bCryptPasswordEncoder.encode(Const.DEFAULT_PASSWORD);
        user.setPassword(passEncoder);
        boolean result = userService.save(user);
        return result;
    }

    /**
     * 给用户分配角色
     * @param id 用户id
     * @param roleIds  角色id列表
     * @return
     */
    @PreAuthorize("hasAuthority('sys:user:role')")
    @PostMapping("/role/{id}")
    public boolean role(@PathVariable Long id, @RequestBody List<Long> roleIds) {
        userRoleService.remove(new QueryWrapper<UserRole>().eq("user_id", id));
        List<UserRole> list = new ArrayList<>();
        roleIds.forEach(roleId -> {
            list.add(new UserRole(id, roleId));
        });
        boolean result = userRoleService.saveBatch(list);
        return result;
    }

    /**
     * 修改用户
     * @param user
     * @return
     */
    @PreAuthorize("hasAuthority('sys:user:update')")
    @PostMapping("/update")
    public boolean updateUserInfo(@RequestBody User user) {
        Integer count = userService.updateUserById(user);
        return count > 0;
    }

    @PreAuthorize("hasAuthority('sys:user:delete')")
    @PostMapping("/delete")
    public boolean delete(@RequestBody List<Long> ids) {
        if (ids.size() == 0) {
            throw new APIException("A0402", "id");
        }

        return userService.removeByIds(ids);
    }

    @PostMapping("/repass")
    public boolean repass(@RequestBody Long id) {
        User user = userService.getById(id);
        if (user == null) {
            throw new APIException("A0408", "用户不存在");
        }
        user.setPassword(bCryptPasswordEncoder.encode(Const.DEFAULT_PASSWORD));
        Integer row = userService.updateUserById(user);
        return row > 0;
    }

    @PostMapping("/updateUserPass")
    public boolean updateUserPass(@RequestBody UserPass userPass) {
        User user = userService.getById(userPass.getId());
        String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        // 1. 确保用户只能修改自己的密码
        if (!username.equals(user.getUsername())) {
            throw new APIException("A0301");
        }
        // 2. 判断两次输入的密码是否匹配
        if (!userPass.getNewPass().equals(userPass.getCheckPass())) {
            throw new APIException("A0423");
        }
        // 3. 判断传入的旧密码是否和用户的密码匹配
        boolean matches = bCryptPasswordEncoder.matches(userPass.getOldPass(), user.getPassword());
        if (!matches) {
            throw new APIException("A0412");
        }
        // 4. 更新密码
        user.setPassword(bCryptPasswordEncoder.encode(userPass.newPass));
        userService.updateUserById(user);
        return true;
    }

    @Data
    public static class UserPass {
        private Long id;
        private String oldPass;
        private String newPass;
        private String checkPass;
    }
}

